//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef __FRAMEBUFFER_H__
#define __FRAMEBUFFER_H__

#include <elasys_server.h>
#include <display.h>
#include <sdl.h>

typedef struct {
    int Width;
    int Height;
    int PosX;
    int PosY;
//    WORD *OverlapFb;
}overlapFormat;

class CFrameBuffer
{
public:
    void ClearBaseplane();

    void GetBaseplaneAddress(
        /* [out] */ Address * pAddress,
        /* [out] */ UInt32 * pAddressId);

    void GetBaseplaneFormat(
        /* [out] */ FrameBufferFormat * pFormat);

    void GetOverlayFormat(
        /* [in] */ Int32 layer,
        /* [out] */ OverlayFormat * pFormat);

    ECode StartDrawing();
    void Render()     { m_bRender     = TRUE; }
    void AutoRender() { m_bAutoRender = TRUE; }

    void UpdateToSurface();
    void UpdateToSurface(Int32 x,Int32 y,Int32 width,Int32 height);

public:
    CFrameBuffer(Int32 posX = 0,
                 Int32 posY = 0,
                 Int32 width = 240,
                 Int32 height = 320,
                 Int32 colorFormat = COLOR_RGB24);
    ~CFrameBuffer();

    ECode Initialize();
    ECode InitializeBaseplane();

private:
    void BaseplaneBufferCopy_RGB888(Int32 x,Int32 y,Int32 width,Int32 height);
    void BaseplaneBufferCopy_RGB565(Int32 x,Int32 y,Int32 width,Int32 height);
    void BaseplaneBufferCopy_RGBT555(Int32 x,Int32 y,Int32 width,Int32 height);
    void BaseplaneBufferCopy_RGBT666(Int32 x,Int32 y,Int32 width,Int32 height);
    void SetBasePlaneColorFormat(ColorFormat CFormat);

    void BaseplaneOverlayCopy_888to888(void);
    void BaseplaneOverlayCopy_555to888(void);
    void BaseplaneOverlayCopy_565to888(void);
    void BaseplaneOverlayCopy_666to888(void);

private:
    UInt32 m_drawSurfaceInterval;
    Int32 m_mobilePosX;
    Int32 m_mobilePosY;
    Int32 m_mobileWidth;
    Int32 m_mobileHeight;

    Int32 m_screenPosX;
    Int32 m_screenPosY;
    Int32 m_screenWidth;
    Int32 m_screenHeight;

    Int32 m_screenColorBits;
    Int32 m_nTransparencyKey;

    Boolean m_bIsOverlay;     //When overlay is setted, there must overlay1 or overlay2 be setted
    Boolean m_bIsSetOverlay1; //When bIsSetOverlay1 is TURE, bIsOverlay must be TURE
    Boolean m_bIsSetOverlay2; //When bIsSetOverlay2 is TURE, bIsOverlay must be TURE
    Boolean m_bIsUnderlay;    //TURE : Underlay

    Boolean m_bShowLCDOnly;

    // framebuffer for base plane;
    ColorFormat m_bpColorFormat;
    Int32 m_bpPixelBits;
    Int32 m_bpPixelBytes;
    void* m_bpBufferAddress;  //framebuffer address of base plane
    UInt32 m_bpBufferAddressId;
    Int32 m_bpBufferSize;
    void (CFrameBuffer::*m_bpBufferCopyFunc)(Int32 x,Int32 y,Int32 width,Int32 height);
    //BaseplaneBufferCopyFunc m_bpBufferCopyFunc;

    // framebuffer for overlavy1 plane;
    OverlayFormat m_overlay1;
    Int32 m_nOverlay1PixelBytes;
    void* m_pOverlay1Fb; //framebuffer address of Overlay1 plane
    UInt32  m_nOverlay1Size;  //framebuffer size (bytes)

    // framebuffer for overlavy2 plane;
    OverlayFormat m_overlay2;
    void* m_pOverlay2Fb; // framebuffer address of YCbCr Overlay2
    UInt32 m_nOverlay2Size;   // framebuffer size (bytes)

    Byte* m_pTransArray; //Transparence Array used to record the baseplane transparence bits
    UInt32 m_nTransArraySize; // Transparence Array size

    overlapFormat m_overlapArea;//The Area is overlaped by three layer

    Boolean m_bBasePlaneInit;

    Boolean m_bRender;
    Boolean m_bAutoRender;

    SDL_Surface * m_pSurface;
    //SDL_Cursor  * m_pCursor;
    SDL_TimerID   m_timerId;
};

// color format exchange

// RGB32 -> others
#define ColorRGB888ToRGB565(color) (WORD)(((color&0x00F80000)>>8) | \
                                ((color&0x0000FC00)>>5) | \
                                ((color&0x000000F8)>>3))

#define ColorRGB888ToRGBT555(color) (WORD)(((color&0x00F80000)>>9) | \
                                ((color&0x0000F800)>>6) | \
                                ((color&0x000000F8)>>3))

#define ColorRGB888ToRGBT666(color) (DWORD)(((color&0x00FC0000)>>6) | \
                                ((color&0x0000FC00)>> 4) | \
                                ((color&0x000000FC)>>2))

// RGB565 -> others
#define ColorRGB565ToRGB888(color) (DWORD)((((DWORD)color&0xF800)<<8) | \
                                (((DWORD)color&0x07E0)<< 5) | \
                                (((DWORD)color&0x001F)<<3))

#define ColorRGB565ToRGBT555(color) (WORD)(((color&0xFFE0)>>1) | \
                                (color&0x001F))

#define ColorRGB565ToRGBT666(color)  (DWORD)((((DWORD)color&0xF800)<<2) | \
                                (((DWORD)color&0x07FF)<<1))

// RGB555 -> others
#define ColorRGBT555ToRGB888(color) (DWORD)((((DWORD)color&0x7C00)<<9) | \
                                (((DWORD)color&0x03E0)<<6) | \
                                (((DWORD)color&0x001F)<<3))

#define ColorRGBT555ToRGB565(color) (WORD)((((WORD)color&0xFFE0) << 1) | \
                                ((WORD)color & 0x001F))

#define ColorRGBT555ToRGBT666(color) (DWORD)((((DWORD)color&0x7C00)<<3) | \
                                (((DWORD)color&0x03E0)<<2) | \
                                (((DWORD)color&0x001F)<<1))

// RGB666 -> others
#define ColorRGBT666ToRGB888(color) (DWORD)(((color&0x03F000) << 6) | \
                                ((color&0x0FC0)<<4) | \
                                ((color&0x3F)<<2))

#define ColorRGBT666ToRGB565(color) (WORD)(((color&0x03E000) >> 2) | \
                                ((color&0x0FFF)>>1))

#define ColorRGBT666ToRGBT555(color) (WORD)(((color&0x03E000) >> 3) | \
                                ((color&0x0F80)>>2) | \
                                ((color&0x3E)>>1))

#endif //__FRAMEBUFFER_H__
